package com.softhinker.ke24.unit1;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.net.URL;
import java.text.BreakIterator;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Observable;
import java.util.Observer;
import java.util.ResourceBundle;
import java.util.Map;
import java.util.Iterator;

import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import com.jgoodies.looks.plastic.PlasticXPLookAndFeel;
import com.softhinker.ke24.unit1.validator.NotEmptyValidator;
import com.softhinker.ke24.unit1.validator.Validatable;

import CLIPSJNI.Environment;
import CLIPSJNI.PrimitiveValue;

public class MainFace extends JFrame implements ActionListener, Validatable {
	private static final long serialVersionUID = 609581834719299553L;
	private ResourceBundle resources;
	private Environment clips;

	private String name;
	private String gender;
	private String birthday;
	private String constellation;

//	private JFrame frame;
	private JButton nextButton;
	private JButton prevButton;
	private JPanel choicesPanel;
	private ButtonGroup choicesButtons;
	private JLabel displayLabel;
	private JTextField answerField;
	private JTextField nameField;
	private JComboBox dropdown;

	private boolean isExecuting = false;
	private Thread executionThread;
	private boolean isValid = false;

	private JRadioButton maleOption;
	private JRadioButton femaleOption;
	private final ObservingTextField birthdayField = new ObservingTextField();
	
	private Color backgroundColor = Color.WHITE;
	
	public MainFace() {
		resources = ResourceBundle.getBundle("LocalizableResource",
				Locale.ENGLISH);

		try {
			UIManager.setLookAndFeel(new PlasticXPLookAndFeel());
		} catch (UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}
		URL url = this.getClass().getResource("/images/icon.png");
		ImageIcon frameIcon = new ImageIcon(url);
		this.setIconImage(frameIcon.getImage());
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		this.getContentPane().setLayout(new GridLayout(3, 1));

		// Center the window
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		int height = screenSize.height;
		int width = screenSize.width;
		this.setSize(width / 2, height / 2);
		this.setLocationRelativeTo(null);
		this.setMinimumSize(new Dimension(650, 500));

		this.setTitle(resources.getString("title"));
		loadCover();
		this.pack();
		this.setVisible(true);
	}

	private void loadCover()
	{
		Cover cover = new Cover();
		
        add(cover);

        JPanel bottom = new JPanel();
        URL url = this.getClass().getResource("/images/go.png");
        ImageIcon img = new ImageIcon(url);
        final JButton start = new JButton(img);
        start.setBorder(null);
        start.setMargin(new Insets(0,0,0,0));
        start.setPressedIcon(new ImageIcon(this.getClass().getResource("/images/go1.png")));
        start.setRolloverIcon(new ImageIcon(this.getClass().getResource("/images/go1.png")));
        
        start.addMouseListener(new MouseListener(){

			public void mouseClicked(MouseEvent e) {
				getContentPane().removeAll();
				init();
			}

			public void mousePressed(MouseEvent e) {
			}

			public void mouseReleased(MouseEvent e) {
				start.setIcon(new ImageIcon(this.getClass().getResource("/images/go.png")));
			}

			public void mouseEntered(MouseEvent e) {
			}

			public void mouseExited(MouseEvent e) {
			}
        	
        });

        bottom.add(start);
        cover.add(bottom);
        
        setLocationRelativeTo(null);
	}
	
	private void init() {
		JPanel displayPanel = new JPanel();
		displayPanel.setBackground(backgroundColor);
		displayPanel.setAlignmentX(LEFT_ALIGNMENT);
		displayPanel.setLayout(new FlowLayout());
		
		URL headerIconUrl = this.getClass().getResource("/images/header_icon.png");
		ImageIcon headerIcon = new ImageIcon(headerIconUrl);
		JLabel headerIconLabel = new JLabel(headerIcon);
		displayPanel.add(headerIconLabel);
		
		displayLabel = new JLabel();
		displayLabel.setFont(new Font("Arial", Font.BOLD,18));
		displayLabel.setForeground(Color.BLACK);
		displayPanel.add(displayLabel);

		JPanel buttonPanel = new JPanel();
		buttonPanel.setAlignmentY(BOTTOM_ALIGNMENT);
		buttonPanel.setBackground(backgroundColor);
		URL prevIconUrl = this.getClass().getResource("/images/prev.png");
		ImageIcon prevIcon = new ImageIcon(prevIconUrl);
		prevButton = new JButton(prevIcon);
		prevButton.setBorder(null);
		prevButton.setMargin(new Insets(0,0,0,0));
		prevButton.setRolloverIcon(new ImageIcon(this.getClass().getResource("/images/prev1.png")));
		prevButton.setPressedIcon(new ImageIcon(this.getClass().getResource("/images/prev1.png")));
		prevButton.setActionCommand("Prev");
		buttonPanel.add(prevButton);
		prevButton.addActionListener(this);

		URL nextIconUrl = this.getClass().getResource("/images/next.png");
		ImageIcon nextIcon = new ImageIcon(nextIconUrl);
		nextButton = new JButton(nextIcon);
		nextButton.setBorder(null);
		nextButton.setMargin(new Insets(0,0,0,0));
		nextButton.setRolloverIcon(new ImageIcon(this.getClass().getResource("/images/next1.png")));
		nextButton.setPressedIcon(new ImageIcon(this.getClass().getResource("/images/next1.png")));
		nextButton.setActionCommand("Next");
		buttonPanel.add(nextButton);
		nextButton.addActionListener(this);

		choicesPanel = new JPanel();
		choicesPanel.setAlignmentY(CENTER_ALIGNMENT);
		choicesPanel.setBackground(backgroundColor);
		choicesButtons = new ButtonGroup();

		this.getContentPane().add(displayPanel);
		this.getContentPane().add(choicesPanel);
		this.getContentPane().add(buttonPanel, BorderLayout.SOUTH);

		loadCLIPS();
	}

	private void loadCLIPS() {
		clips = new Environment();
		clips.load("Common.clp");
		clips.load("Database.clp");
		clips.load("Appearance.clp");
		clips.load("Background.clp");
		clips.load("Personality.clp");
		clips.load("Horoscope.clp");
		clips.reset();
		
		/*Person person = new Person(clips,"Megan Fox");
		System.out.println("Gender: " +person.getGender());
		System.out.println("Body: " +person.getBody());
		System.out.println("Education: " +person.getEducation());
		System.out.println("Career: " +person.getCareer());
		System.out.println("Personality: " +person.getPersonality());
		*/
		
		startReasoning();
	}

	public void actionPerformed(ActionEvent ae) {
		if (isExecuting || !isValid || this.birthdayField.getText() == null || "".equals(this.birthdayField.getText()))
			return;

		String evalStr = "(find-all-facts ((?f state-list)) TRUE)";

		String currentID = null;
		try {
			currentID = clips.eval(evalStr).get(0).getFactSlot("current")
					.toString();
		} catch (Exception e) {
			e.printStackTrace();
			return;
		}
		System.out.println("currentID = " + currentID);

		evalStr = "(find-all-facts ((?f UI-state)) " + "(eq ?f:id " + currentID
				+ "))";
		
		PrimitiveValue uiState = null;
		String answerType = null;
		try {
			uiState = clips.eval(evalStr).get(0);
			PrimitiveValue answerTypeAttribute = uiState.getFactSlot("answer-type");
			answerType = answerTypeAttribute.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		/* ========================= */
		/* Handle the Next button. */
		/* ========================= */

		if (ae.getActionCommand().equals("Next")) {
			
			/********************************************************/
			//added by tan, process the 1st screen, assert gender and birth date
			PrimitiveValue stateAttribute = null;
			try {
				uiState = clips.eval(evalStr).get(0);
				stateAttribute = uiState.getFactSlot("state");
			} catch (Exception e) {
				e.printStackTrace();
			}
			
			if (stateAttribute.toString().equals("initial")){
				this.name = this.nameField.getText();
				this.birthday = this.birthdayField.getText();
				if(this.birthday != null && !"".equals(this.birthday))
				{
					DateFormat sdf = SimpleDateFormat.getDateInstance(SimpleDateFormat.LONG,
		                    Locale.ENGLISH);
					try {
						Date date = sdf.parse(this.birthday);
						ConstellationHelper constellationHelper = new ConstellationHelper();
						this.constellation = constellationHelper.getConstellation(date);
						System.out.println("Constellation is : " + this.constellation);
						clips.assertString("(constellation " + this.constellation + ")");
					} catch (ParseException e) {
						e.printStackTrace();
						return;
					}
				}
				
				System.out.println("The name is : " + this.name);
				if (maleOption.isSelected()){
					this.gender = "m";
				}else{
					this.gender = "f";
				}
				clips.assertString("(target_gender "+ gender + ")");
				System.out.println("target_gender = " + gender);
				
			}
			/*****************************************************/
			
			if (choicesButtons.getButtonCount() == 0) {
				if("multi-choice".equals(answerType))
				{
					clips.assertString("(next " + currentID + ")");
					System.out.println("assertString = " + "(next " + currentID + ")");
				}
				else if("text".equals(answerType))
				{
					clips.assertString("(next " + currentID + " "
							+ this.answerField.getText()
							+ ")");
					System.out.println("assertString = " + "(next " + currentID + " " +
							this.answerField.getText() + 
	                        ")");
				}
				else if("dropdown".equals(answerType))
				{
					int selectedIndex = dropdown.getSelectedIndex() + 1;
					String selectedCareer = "career" + Integer.toString(selectedIndex);
					clips.assertString("(next " + currentID + " "
							+ selectedCareer
							+ ")");
					System.out.println("assertString = " + "(next " + currentID + " " +
							selectedCareer + 
	                        ")");
				}
			} else {
				clips.assertString("(next " + currentID + " "
						+ choicesButtons.getSelection().getActionCommand()
						+ ")");
				System.out.println("assertString = " + "(next " + currentID + " " +
                        choicesButtons.getSelection().getActionCommand() + 
                        ")");
			}

			startReasoning();
		} else if (ae.getActionCommand().equals("Restart")) {
			clips.reset();
			startReasoning();
		} else if (ae.getActionCommand().equals("Prev")) {
			clips.assertString("(prev " + currentID + ")");
			startReasoning();
		}
		
		/* ===================== */
		/* Get the state-list. */
		/* ===================== */

	}

	private void nextUIState() throws Exception {
		//added by michael for testing
//		System.out.println("===========================FACTS==========================");
//		try{
//			clips.eval("(facts)");
//			clips.eval("(watch activations)");
//		}catch(Exception e){
//			e.printStackTrace();
//		}
//		System.out.println("==========================================================");
		//ended
		
		/* ===================== */
		/* Get the state-list. */
		/* ===================== */

		String evalStr = "(find-all-facts ((?f state-list)) TRUE)";

		String currentID = clips.eval(evalStr).get(0).getFactSlot("current")
				.toString();

		/* =========================== */
		/* Get the current UI state. */
		/* =========================== */

		evalStr = "(find-all-facts ((?f UI-state)) " + "(eq ?f:id " + currentID
				+ "))";
		
		System.out.println("evalStr : " + evalStr);
		
		PrimitiveValue uiState = clips.eval(evalStr).get(0);
		PrimitiveValue stateAttribute = uiState.getFactSlot("state");

		// Clear the current content on choicesPanel
		choicesPanel.removeAll();
		choicesButtons = new ButtonGroup();

		/* ======================================== */
		/* Determine the Next/Prev button states. */
		/* ======================================== */

		System.out.println("state = " + stateAttribute.toString());

//		if ("final_0".equals(stateAttribute.toString())
//				|| "final_1".equals(stateAttribute.toString()) 
//				|| "final_2".equals(stateAttribute.toString()) 
//				|| "final_3".equals(stateAttribute.toString()))
		if ("final".equals(stateAttribute.toString()))
		{
			nextButton.setActionCommand("Restart");
			nextButton.setIcon(new ImageIcon(this.getClass().getResource("/images/restart.png")));
			nextButton.setPressedIcon(new ImageIcon(this.getClass().getResource("/images/restart1.png")));
			nextButton.setRolloverIcon(new ImageIcon(this.getClass().getResource("/images/restart1.png")));
			prevButton.setVisible(false);
			
			String findResult = "(find-all-facts ((?f final)) TRUE)";
			PrimitiveValue results = clips.eval(findResult);
			for(int i=0;i<results.size();i++)
			{
				PrimitiveValue fact = results.get(i);
				
				if(i>3)
				{
					break;
				}
				else
				{
					String name = fact.getFactSlot("name").toString();
					name = name.replaceAll("\"", "");
					String cf = fact.getFactSlot("cf").toString();

					String iconPath = "/images/recommendation/"+name+".jpg";
										if ((i==0)&&(Integer.parseInt(cf) <61))
						{
						iconPath = "/images/recommendation/nomatch.jpg";
						}
					System.out.println("Recommendation icon : " + iconPath);
					
					URL url = this.getClass().getResource(iconPath);
					ImageIcon recommendationIcon = new ImageIcon(url);
					JLabel recommendation = new JLabel(recommendationIcon);
					
					Person person = new Person(clips, name);
					StringBuffer reason = new StringBuffer();
					
					reason.append("<html>");
					reason.append("<h2><center><font color='red'>" + person.getName() + "</font></center></h2>");
					reason.append("<h3>Personal Information</h3>");
					reason.append("<table border='0' width='350px'>");
					reason.append("<tr><td width='30%'><b>Recommendation :</b></td><td> " + cf + "%</td></tr>");
					reason.append("<tr><td><b>Body Shape :</b></td><td> " + person.getBody() + "</td></tr>");
					reason.append("<tr><td><b>Education level :</b></td> <td>" + person.getEducation() + "</td></tr>");
					reason.append("<tr><td><b>Occupation :</b></td><td> " + person.getCareer() + "</td></tr>");
					reason.append("<tr><td><b>Personality :</b></td><td> " + person.getPersonality().getTitle() + " (" + person.getPersonality() + ")</td></tr>");
					reason.append("</table>");
					reason.append("<h3>Reason for matching</h3>");
					
					//Appearance
					Map<String,String> appr = person.getReasonForAppearance();
					Iterator<String> itAppr = appr.keySet().iterator();
					if (appr.size()>0){
						reason.append("<h4>Appearance:</h4>");
						reason.append("<table border='0' width='350px'>");
						System.out.println("Appearance");
						while (itAppr.hasNext()){
							reason.append("<tr>");
							String subcategory = itAppr.next();
							String reasonDesc = appr.get(subcategory);
							System.out.println(subcategory.replaceAll("\"","") + ":" + reasonDesc.replaceAll("\"",""));
							reason.append("<td width='30%'><b>");
							reason.append(subcategory.replaceAll("\"","") + ":");
							reason.append("</b></td>");
							reason.append("<td width='70%'>");
							reason.append(reasonDesc.replaceAll("\"",""));
							reason.append("</td>");
							reason.append("</tr>");
						}
						reason.append("</table>");	
					}
					
					//Background
					Map<String,String> bgrd = person.getReasonForBackground();
					Iterator<String> itBgrd = bgrd.keySet().iterator();
					if (bgrd.size() > 0){
						reason.append("<h4>Background</h4>");
						reason.append("<table border='0' width='350px'>");
						System.out.println("Background:");
						while (itBgrd.hasNext()){
							reason.append("<tr>");
							String subcategory = itBgrd.next();
							String reasonDesc = bgrd.get(subcategory);
							System.out.println(subcategory.replaceAll("\"","") + ":" + reasonDesc.replaceAll("\"",""));
							reason.append("<td width='30%'><b>");
							reason.append(subcategory.replaceAll("\"","") + ":");
							reason.append("</b></td>");
							reason.append("<td width='70%'>");
							reason.append(reasonDesc.replaceAll("\"",""));
							reason.append("</td>");
							reason.append("</tr>");
						}
						reason.append("</table>");
					}
					
					//Personality
					
					Map<String,String> psnlt = person.getReasonForPersonality();
					Iterator<String> itPsnlt = psnlt.keySet().iterator();
					if (psnlt.size()>0){
						reason.append("<h4>Personality</h4>");
						reason.append("<table border='0' width='350px'>");
						System.out.println("Personality:");
						while (itPsnlt.hasNext()){
							reason.append("<tr>");
							String subcategory = itPsnlt.next();
							String reasonDesc = psnlt.get(subcategory);
							System.out.println(subcategory.replaceAll("\"","") + ":" + reasonDesc.replaceAll("\"",""));
							reason.append("<td width='30%'><b>");
							reason.append(subcategory.replaceAll("\"","") + ":");
							reason.append("</b></td>");
							reason.append("<td width='70%'>");
							reason.append(reasonDesc.replaceAll("\"",""));
							reason.append("</td>");
							reason.append("</tr>");
						}
						reason.append("</table>");
					}
					//Appearance
					
					Map<String,String> horo = person.getReasonForHoroscope();
					Iterator<String> itHoro = horo.keySet().iterator();
					if (horo.size()> 0){
						reason.append("<h4>Horoscope</h4>");
						reason.append("<table border='0' width='350px'>");
						System.out.println("Horoscope:");
						while (itHoro.hasNext()){
							reason.append("<tr>");
							String subcategory = itHoro.next();
							String reasonDesc = horo.get(subcategory);
							System.out.println(subcategory.replaceAll("\"","") + ":" + reasonDesc.replaceAll("\"",""));
							reason.append("<td width='30%'><b>");
							reason.append(subcategory.replaceAll("\"","") + ":");
							reason.append("</b></td>");
							reason.append("<td width='70%'>");
							reason.append(reasonDesc.replaceAll("\"",""));
							reason.append("</td>");
							reason.append("</tr>");
						}
						reason.append("</table>");
					}
					reason.append("</html>");
					recommendation.setToolTipText(reason.toString());
					
					choicesPanel.add(recommendation);
				}
			}
			
		} else if (stateAttribute.toString().equals("initial")) {
			//First page when launching the application.
			nextButton.setActionCommand("Next");
			nextButton.setIcon(new ImageIcon(this.getClass().getResource("/images/next.png")));
			nextButton.setPressedIcon(new ImageIcon(this.getClass().getResource("/images/next1.png")));
			nextButton.setRolloverIcon(new ImageIcon(this.getClass().getResource("/images/next1.png")));
			prevButton.setVisible(false);

			JPanel hardConstraintPanel = new JPanel();
			hardConstraintPanel.setLayout(new GridLayout(3, 2));
			hardConstraintPanel.setBackground(backgroundColor);

			JLabel nameLabel = new JLabel(resources.getString("label.name")
					+ " : ");
			nameLabel.setFont(new Font("Arial", Font.PLAIN, 16));
			JPanel namePanel = new JPanel();
			namePanel.setBackground(backgroundColor);
			nameField = new JTextField(18);
			nameField.setText(this.name);
			nameField.setInputVerifier(new NotEmptyValidator(this, nameField, "Field cannot be empty!"));
			namePanel.add(nameField);

			JLabel genderLabel = new JLabel(resources.getString("label.gender")
					+ " : ");
			genderLabel.setFont(new Font("Arial", Font.PLAIN, 16));
			JPanel genderPanel = new JPanel();
			genderPanel.setBackground(backgroundColor);
			ButtonGroup genderGroup = new ButtonGroup();
			maleOption = new JRadioButton(
					resources.getString("gender.male"));
			maleOption.setFont(new Font("Arial", Font.PLAIN, 16));
			maleOption.setBackground(backgroundColor);
			if(this.gender == null || "m".equals(this.gender))
				maleOption.setSelected(true);
			femaleOption = new JRadioButton(
					resources.getString("gender.female"));
			femaleOption.setBackground(backgroundColor);
			femaleOption.setFont(new Font("Arial", Font.PLAIN, 16));
			if("f".equals(this.gender))
				femaleOption.setSelected(true);
			
			genderGroup.add(maleOption);
			genderGroup.add(femaleOption);
			genderLabel.setLabelFor(genderPanel);
			genderPanel.add(maleOption);
			genderPanel.add(femaleOption);

			JLabel birthdayLabel = new JLabel(
					resources.getString("label.birthday") + " : ");
			birthdayLabel.setFont(new Font("Arial", Font.PLAIN, 16));
			JPanel birthdayPanel = new JPanel();
			birthdayPanel.setBackground(backgroundColor);
			final JFrame datePickerFrame = new JFrame();
			datePickerFrame.getContentPane().setLayout(new FlowLayout());
			datePickerFrame.setSize(300, 150);
			Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
			datePickerFrame.setLocation(
					(int) (dim.getWidth() - datePickerFrame.getWidth()) / 2,
					(int) (dim.getHeight() - datePickerFrame.getHeight()) / 2);
			datePickerFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			datePickerFrame.setBackground(backgroundColor);

			// create a text-field that implements Observer
			
			birthdayField.setColumns(10);
			birthdayField.setText(this.birthday);
			birthdayField.setEditable(false);
			birthdayField.setInputVerifier(new NotEmptyValidator(this, birthdayField, "Field cannot be empty!"));
			birthdayField.setBackground(backgroundColor);

			// create a button
			final Locale locale = Locale.ENGLISH;
			final JButton btn = new JButton(new ImageIcon(this.getClass().getResource("/images/pickdate.png")));
			btn.setBorder(null);
			btn.setMargin(new Insets(0,0,0,0));
			btn.setPressedIcon(new ImageIcon(this.getClass().getResource("/images/pickdate1.png")));
			btn.setRolloverIcon(new ImageIcon(this.getClass().getResource("/images/pickdate1.png")));
			btn.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					// instantiate the DatePicker
					DatePicker dp = new DatePicker(birthdayField, locale);
					// previously selected date
					Date selectedDate = dp.parseDate(birthdayField.getText());
					dp.setSelectedDate(selectedDate);
					dp.start(birthdayField);
				};
			});
			datePickerFrame.setVisible(false);
			birthdayPanel.add(birthdayField);
			birthdayPanel.add(btn);
			datePickerFrame.getContentPane().add(birthdayPanel);

			hardConstraintPanel.add(nameLabel);
			hardConstraintPanel.add(namePanel);
			hardConstraintPanel.add(genderLabel);
			hardConstraintPanel.add(genderPanel);
			hardConstraintPanel.add(birthdayLabel);
			hardConstraintPanel.add(birthdayPanel);

			choicesPanel.add(hardConstraintPanel);

		} else {
			nextButton.setActionCommand("Next");
			nextButton.setIcon(new ImageIcon(this.getClass().getResource("/images/next.png")));
			nextButton.setPressedIcon(new ImageIcon(this.getClass().getResource("/images/next1.png")));
			nextButton.setRolloverIcon(new ImageIcon(this.getClass().getResource("/images/next1.png")));
			prevButton.setVisible(true);
		}

		/* ===================== */
		/* Set up the choices. */
		/* ===================== */

		PrimitiveValue validAnswersAttribute = uiState
				.getFactSlot("valid-answers");
		PrimitiveValue answerTypeAttribute = uiState.getFactSlot("answer-type");

		String selected = uiState.getFactSlot("response").toString();

		if ("multi-choice".equals(answerTypeAttribute.toString())) {
			String sex = null;
			if("favtype_female1".equals(uiState.getFactSlot("display").symbolValue()))
				sex = "female";
			else if("favtype_male1".equals(uiState.getFactSlot("display").symbolValue()))
				sex = "male";
			
			for (int i = 0; i < validAnswersAttribute.size(); i++) {
				PrimitiveValue option = validAnswersAttribute.get(i);
				JRadioButton rButton;
				System.out.println("option " + i + " = " + option.toString());
				if (option.toString().equals(selected)) {
					if("female".equals(sex) || "male".equals(sex))
					{
						String picName = resources.getString(option.toString());
						picName = picName.trim();
						URL url = this.getClass().getResource("/images/gendertype/"+picName.toLowerCase()+".jpg");
						ImageIcon radioIcon = new ImageIcon(url);
						rButton = new JRadioButton(radioIcon, true);
						rButton.setBackground(backgroundColor);
						rButton.setFont(new Font("Arial", Font.PLAIN, 16));
						rButton.setPressedIcon(new ImageIcon(
								this.getClass().getResource("/images/gendertype/"+picName.toLowerCase()+".jpg")));
						rButton.setRolloverEnabled(true);
						rButton.setRolloverIcon(new ImageIcon(
								this.getClass().getResource("/images/gendertype/"+picName.toLowerCase()+".jpg")));
						rButton.setSelectedIcon(new ImageIcon(
								this.getClass().getResource("/images/gendertype/"+picName.toLowerCase()+".jpg")));
						rButton.addActionListener(new ActionListener(){

							public void actionPerformed(ActionEvent e) {
								Enumeration<AbstractButton> buttons = choicesButtons.getElements();
								while(buttons.hasMoreElements())
								{
									AbstractButton button = buttons.nextElement();
									if(!button.isSelected())
									{
										String pic = button.getActionCommand();
										button.setIcon(new ImageIcon(
												getClass().getResource("/images/gendertype/"+pic.toLowerCase()+"1.jpg")));
									}
								}
							}
							
						});
					}
					else
						rButton = new JRadioButton(resources.getString(option
								.toString()), true);
						rButton.setBackground(backgroundColor);
						rButton.setFont(new Font("Arial", Font.PLAIN, 16));
					
				} else {
					if("female".equals(sex) || "male".equals(sex))
					{
						String picName = resources.getString(option.toString());
						URL url = this.getClass().getResource("/images/gendertype/"+picName.toLowerCase()+"1.jpg");
						ImageIcon radioIcon = new ImageIcon(url);
						rButton = new JRadioButton(radioIcon, false);
						rButton.setBackground(backgroundColor);
						rButton.setFont(new Font("Arial", Font.PLAIN, 16));
						rButton.setPressedIcon(new ImageIcon(
								this.getClass().getResource("/images/gendertype/"+picName.toLowerCase()+".jpg")));
						rButton.setRolloverEnabled(true);
						rButton.setRolloverIcon(new ImageIcon(
								this.getClass().getResource("/images/gendertype/"+picName.toLowerCase()+".jpg")));
						rButton.setSelectedIcon(new ImageIcon(
								this.getClass().getResource("/images/gendertype/"+picName.toLowerCase()+".jpg")));
						rButton.addActionListener(new ActionListener(){

							public void actionPerformed(ActionEvent e) {
								Enumeration<AbstractButton> buttons = choicesButtons.getElements();
								while(buttons.hasMoreElements())
								{
									AbstractButton button = buttons.nextElement();
									if(!button.isSelected())
									{
										String pic = button.getActionCommand();
										button.setIcon(new ImageIcon(
												getClass().getResource("/images/gendertype/"+pic.toLowerCase()+"1.jpg")));
									}
								}
							}
							
						});
					}
					else
					{
						rButton = new JRadioButton(resources.getString(option
								.toString()), false);
						rButton.setBackground(backgroundColor);
						rButton.setFont(new Font("Arial", Font.PLAIN, 16));
					}
				}

				rButton.setActionCommand(option.toString());
				choicesPanel.add(rButton);
				choicesButtons.add(rButton);
			}
		}
		else if("text".equals(answerTypeAttribute.toString()))
		{
			answerField = new JTextField(20);
			answerField.setBackground(backgroundColor);
			if(!"none".equals(selected))
				answerField.setText(selected);
			choicesPanel.add(answerField);
		}
		else if("dropdown".equals(answerTypeAttribute.toString()))
		{
			String[] optionValues = new String[validAnswersAttribute.size()];
			for(int i=0;i<validAnswersAttribute.size();i++)
			{
				PrimitiveValue option = validAnswersAttribute.get(i);
				optionValues[i] = resources.getString(option.toString());
			}
			
			dropdown = new JComboBox(optionValues);
			dropdown.setBackground(backgroundColor);
			dropdown.setFont(new Font("Arial", Font.PLAIN, 16));
			if(selected != null && !"".equals(selected))
			{
				String selectedIndex = selected.substring("career".length());
				if(selectedIndex != null && !"".equals(selectedIndex))
					dropdown.setSelectedIndex(Integer.parseInt(selectedIndex) - 1);
				else dropdown.setSelectedIndex(0);
			}
			else dropdown.setSelectedIndex(0);
			choicesPanel.add(dropdown);
		}

		choicesPanel.repaint();

		/* ==================================== */
		/* Set the label to the display text. */
		/* ==================================== */

		String theText = resources.getString(uiState.getFactSlot("display")
				.symbolValue());
		
		if(!stateAttribute.toString().equals("initial"))
		{
			theText = ("m".equalsIgnoreCase(this.gender) ? "Ms. " : "Mr. ") + this.name + ", " + theText;
			System.out.println(theText);
		}
		
		wrapLabelText(displayLabel, theText);

		executionThread = null;

		isExecuting = false;
	}

	private void wrapLabelText(JLabel label, String text) {
		FontMetrics fm = label.getFontMetrics(label.getFont());
		Container container = label.getParent();
		int containerWidth = container.getWidth();
		containerWidth = 485;//hard coded
		int textWidth = SwingUtilities.computeStringWidth(fm, text);
		int desiredWidth;

		if (textWidth <= containerWidth) {
			desiredWidth = containerWidth;
		} else {
			int lines = (int) ((textWidth + containerWidth) / containerWidth);

			desiredWidth = (int) (textWidth / lines);
		}
		BreakIterator boundary = BreakIterator.getWordInstance();
		boundary.setText(text);

		StringBuffer trial = new StringBuffer();
		StringBuffer real = new StringBuffer("<html><center>");

		int start = boundary.first();
		for (int end = boundary.next(); end != BreakIterator.DONE; start = end, end = boundary
				.next()) {
			String word = text.substring(start, end);
			trial.append(word);
			int trialWidth = SwingUtilities.computeStringWidth(fm,
					trial.toString());
			if (trialWidth > containerWidth) {
				trial = new StringBuffer(word);
				real.append("<br>");
				real.append(word);
			} else if (trialWidth > desiredWidth) {
				trial = new StringBuffer("");
				real.append(word);
				real.append("<br>");
			} else {
				real.append(word);
			}
		}

		real.append("</html>");
		label.setText(real.toString());
	}

	public void startReasoning() {
		Runnable runThread = new Runnable() {
			public void run() {
				clips.run();

				SwingUtilities.invokeLater(new Runnable() {
					public void run() {
						try {
							nextUIState();
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				});
			}
		};

		isExecuting = true;

		executionThread = new Thread(runThread);

		executionThread.start();
	}

	public void validateFailed() {
		isValid = false;
	}

	public void validatePassed() {
		isValid = true;
	}
}

class ObservingTextField extends JTextField implements Observer {
	private static final long serialVersionUID = 5644801183503611863L;

	public void update(Observable o, Object arg) {
		Calendar calendar = (Calendar) arg;
		DatePicker dp = (DatePicker) o;
		System.out.println("picked=" + dp.formatDate(calendar));
		setText(dp.formatDate(calendar));
	}
}